/*
 * Copyright 2010 Google Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.websocket;

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Set;

/**
 * WebSocket framing API.
 */
public interface WebSocket {

  /**
   * Callbacks for WebSocket events.
   */
  public interface Callback {

    /**
     * Called when a binary message is received.
     * @param message
     * @param metadata
     * @throws IOException
     */
    void onBinaryMessage(byte[] message, Set<ExtensionData> metadata) throws IOException;

    /**
     * Called when the WebSocket is closed while reading a message.
     */
    void onClose();

    /**
     * Called when a framing error is detected.
     * 
     * TODO: pass more information to this method.
     */
    void onFramingError();

    /**
     * Called when a text message is received.
     *
     * @param message
     * @param metadata
     * @throws IOException
     */
    void onTextMessage(String message, Set<ExtensionData> metadata) throws IOException;
  }

  /**
   * Close the WebSocket.  Sends a graceful close frame to the remote endpoint,
   * and no further frames may be sent.
   * 
   * @throws IOException
   */
  void close() throws IOException;

  /**
   * Process a single message via the supplied callback.
   * 
   * @param callback
   * @throws IOException
   */
  void readOneMessage(Callback callback) throws IOException;

  /**
   * Send an arbitrary stream of binary data as a binary messsage.
   *
   * @param metadata
   * @return an OutputStream to write the message payload to -- it must be
   *     closed before any other non-control messages are written to this
   *     WebSocket 
   * @throws IOException
   */
  OutputStream sendBinaryMessage(Set<ExtensionData> metadata)
      throws IOException;

  /**
   * Send a binary message.
   *
   * @param metadata
   * @param message
   * @throws IOException
   */
  void sendBinaryMessage(Set<ExtensionData> metadata, byte[] message)
      throws IOException;

  /**
   * Write an arbitrarily long text message.
   * 
   * @param metadata
   * @return PrintWriter to write message on; must be closed before sending any
   *     other non-control messages on this WebSocket
   * @throws IOException
   */
  PrintWriter sendTextMessage(Set<ExtensionData> metadata) throws IOException;

  /**
   * Write a text message.
   *
   * @param metadata
   * @param message
   * @throws IOException
   */
  void sendTextMessage(Set<ExtensionData> metadata, String message)
      throws IOException;

}